define(["drawable", "bouncer", "gameconfiguration"], function(Drawable, Bouncer, config){
        
    
    Ball.prototype = new Drawable();
    
    function Ball(sprite) {     
        
        this.sprite = sprite;
        this.maxX = undefined;
        this.maxY = undefined;
        this.maxBouncingAngle = Math.PI/2;        
        this.speed = 3  ;
        this.vector = [1,1];
        this.lastX = undefined;
        this.lastY = undefined;
        this.init(sprite.width, sprite.height);        
        
        this.invertX = function(){
            this.vector[0] *= -1;
        };
        
        this.invertY = function(){
            this.vector[1] *= -1;
        };
        
        this.checkBorderCollision = function(){
            if(this.x >= this.maxX -this.w || this.x <= 0){
                this.invertX();
            }
            if(this.y >= this.maxY - this.h || this.y <= 0){
                this.invertY();
            }
        };
        
        this.calculateBouncingAngle = function(collisionObject){            
            
            if(!config.BouncingAngleDynamic){
                return null;
            }
            
            var bouncingAngle = null;
            if(collisionObject instanceof Bouncer){            
                var bouncer = collisionObject;
                var minBouncingAngle = 0.1;
                var bouncerW2 = bouncer.w/2;
                var ballX = this.getCenterX();
                var distBallToCenter = Math.abs((bouncer.x + bouncerW2) - ballX);                            
                bouncingAngle = this.maxBouncingAngle - (this.maxBouncingAngle/bouncerW2 * distBallToCenter) + minBouncingAngle;
            }
            return bouncingAngle;
        };
        
        this.setBouncingAngle = function(hitSurface, bouncingAngle){
            if(bouncingAngle === null){
                return;
            }               
            if(hitSurface == this.SIDE_BOTTOM || hitSurface == this.SIDE_TOP){
                this.vector[1] = bouncingAngle !== null ? bouncingAngle : this.vector[1];    
                this.vector[0] = this.vector[0] < 0 ? - this.maxBouncingAngle + bouncingAngle : this.maxBouncingAngle - bouncingAngle;
            }
            else if(hitSurface == this.SIDE_RIGHT || hitSurface == this.SIDE_LEFT){
                this.vector[0] = bouncingAngle !== null ? bouncingAngle : this.vector[0];    
                this.vector[1] = this.vector[1] < 0 ? - this.maxBouncingAngle + bouncingAngle : this.maxBouncingAngle - bouncingAngle;
            }
        };
    }
    
    
    
    Ball.prototype.draw = function(context){
        
        if(this.x === undefined){
            this.maxX = context.canvas.width;    
            this.maxY = context.canvas.height;
            this.x = (this.maxX-this.w)/2;
            this.y = (this.maxY-this.h)/2;
        }
                
        context.clearRect(0,0,context.canvas.width, context.canvas.height);
      
        this.lastX = this.x;
        this.lastY = this.y;
        
        this.x += this.speed * this.vector[0];
        this.y += this.speed * this.vector[1];
        
        this.checkBorderCollision();        
        
        context.save();
        context.translate(this.x, this.y);
        context.drawImage(this.sprite, 0, 0 );
        context.restore();                      
    };
    
    Ball.prototype.collides = function(collisionObject){
        
        var bouncingAngle= this.calculateBouncingAngle(collisionObject);
        this.setBouncingAngle(this.collisionSide, bouncingAngle);
        
        if( this.collisionSide == collisionObject.SIDE_TOP || 
            this.collisionSide == collisionObject.SIDE_BOTTOM  ){            
            this.invertY();            
            this.y = this.lastY;            
        }
        else if(    this.collisionSide == collisionObject.SIDE_LEFT || 
                    this.collisionSide == collisionObject.SIDE_RIGHT  ){            
            this.invertX();
            this.x = this.lastX;
        }
    };
    
    
    
    return Ball;
});